#include <chrono>
#include <functional>
#include <memory>
#include <string>

#include <filesystem>
#include <csignal>
#include <cstdlib>
#include <fstream>
#include <iomanip>  // For std::put_time

#include "rclcpp/rclcpp.hpp"
#include "common_lib/glog/glog.h"
#include <backward_ros/backward.hpp>

std::string g_camera_name = "common_test";  // Assuming this is declared elsewhere
void signalHandler(int sig) {
  std::cout << "Received signal: " << sig << std::endl;

  std::string log_dir = "/home/xxty/user_data/gdb/";

  // get current time
  std::time_t now = std::time(nullptr);
  std::tm *local_time = std::localtime(&now);

  // format date and time to string, format as "2024_05_20_12_34_56"
  std::ostringstream time_stream;
  time_stream << std::put_time(local_time, "%Y_%m_%d_%H_%M_%S");

  // generate log file name
  std::string log_file_name = g_camera_name + "_crash_stack_trace_" + time_stream.str() + ".log";
  std::string log_file_path = log_dir + log_file_name;

  if (!std::filesystem::exists(log_dir)) {
    std::filesystem::create_directories(log_dir);
  }

  std::cout << "Log crash stack trace to " << log_file_path << std::endl;
  std::ofstream log_file(log_file_path, std::ios::app);

  if (log_file.is_open()) {
    log_file << "Received signal: " << sig << std::endl;

    backward::StackTrace st;
    st.load_here(32);  // Capture stack
    backward::Printer p;
    // p.print(st, log_file);  // Print stack to log file
    p.print(st, std::cerr);  // Fallback to stderr

    // std::ostringstream ss;
    // backward::StackTrace stackTrace;
    // backward::TraceResolver resolver;
    // stackTrace.load_here(32);
    // resolver.load_stacktrace(stackTrace);
    // for(std::size_t i = 0; i < stackTrace.size(); ++i){
    //     const backward::ResolvedTrace trace = resolver.resolve(stackTrace[i]);
    //     ss << "#" << i << " at " << trace.object_function 
    //       << " in " << trace.object_filename  
    //       << ", source: "<< trace.source.function 
    //       << ", " << trace.source.filename << ":" << trace.source.line << ":" << trace.source.col 
    //       << "\n";
        
    // }
    // cout << ss.str() << endl;
    // // 写入文件中
    // log_file << ss.str() << endl;
  }

  log_file.close();
  exit(sig);  // Exit program
}


class TestBackward : public rclcpp::Node{
    public:
        TestBackward();
        ~TestBackward() = default;

        void test();
};  

TestBackward::TestBackward(): Node("test_backward_node"){
    test();
}

void TestBackward::test(){
    int* p = nullptr;
    *p = 42; // 这会触发SIGSEGV
}

int main(int argc, char * argv[]){
    // signal(SIGSEGV, signalHandler);  // segment fault
    // signal(SIGABRT, signalHandler);  // abort
    // signal(SIGFPE, signalHandler);   // float point exception
    // signal(SIGILL, signalHandler);   // illegal instruction

    // struct sigaction act {};
    // act.sa_flags = SA_NODEFER | SA_RESETHAND;
    // act.sa_handler = &signalHandler;
    // sigfillset(&act.sa_mask);
    // sigdelset(&act.sa_mask, SIGSEGV);
    // if (sigaction(SIGSEGV, &act, nullptr) == -1)
    //     std::exit(EXIT_FAILURE);

    // 使用backward的SignalHandling捕获信号
    // backward::SignalHandling sh;

    rclcpp::init(argc, argv);
    rclcpp::spin(std::make_shared<TestBackward>());
    rclcpp::shutdown();
    return 0;
}